package com.gtp.mq.demo.confirm;

import org.apache.commons.lang.SerializationUtils;
import org.junit.Test;

import com.gtp.mq.demo.QueueBindFactory;
import com.rabbitmq.client.MessageProperties;

/*
 * 目的:了解消息是否真的发送到broker服务器
 * confirm被事务模式性能更好一些！(他是异步的!)
 * 原理:一旦信道进入confirm模式，所有在该信道上面发布的消息都将会被指派一个唯一的ID(从1开始)，
 *     一旦消息被投递到所有匹配的队列之后，broker就会发送一个确认给生产者(包含消息的唯一ID)，
 *     这就使得生产者知道消息已经正确到达目的队列了
 * 确认和事务模式不能共享
 */
public class ConfirmProducer extends QueueBindFactory{

	@Test
	public void test() throws Exception{
		
		//开启发送方确认模式
		channel.confirmSelect();
	
		channel.basicPublish("mytopicExchangeName", // exchange名称
				"r2.123",// 路由key
				true, // 持久化
				MessageProperties.PERSISTENT_TEXT_PLAIN, // 持久化文本消息
				SerializationUtils.serialize("mgs_123"));
		
		channel.basicPublish("mytopicExchangeName", // exchange名称
				"r2.123",// 路由key
				true, // mandatory=true
				MessageProperties.PERSISTENT_TEXT_PLAIN, // 持久化文本消息
				SerializationUtils.serialize("mgs_456"));
		
		//普通模式:1条1确认
//		if(channel.waitForConfirms()){
//			System.out.println("发送成功!");
//		}else{
//			System.out.println("发送失败!");
//		}
		
		//批量方式:批量发送一波，然后等待
		/*
		 * 等到自上次通话以来发布的所有消息都已被经纪人确认或拒绝
		 * 若有未收到的则IOException遗产抛出
		 * 在非确认渠道调用抛出IllegalStateException
		 * 
		 * 缺点:若其中有失败的,那得全部重新发送,有重复消息
		 */
		//channel.waitForConfirms();
		
		//该方法会等到最后一条消息得到确认或者得到nack才会结束，
		//也就是说在waitForConfirmsOrDie处会造成当前程序的阻塞
		//channel.waitForConfirmsOrDie();
		
		//模式3:异步 channel.addConfirmListener
		/*
		 * 详情参阅:baseFactory
		 * 这种情况在回调中不知道什么消息,可以在这里先存储下
		 * channel.getNextPublishSeqNo()->deliveryTag
		 */
		
		//*重试等可能导致重复消息,请业务做好幂等,本来“重复”也只能业务能识别这个语义
		
		System.out.println("ok");
	}
}
